package com.ssy.lingxi.system.service.impl;

import com.ssy.lingxi.common.constant.CommonConstant;
import com.ssy.lingxi.common.constant.member.MemberConfigTagEnum;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.member.merchant.api.feign.paas.MemberConfigControllerFeign;
import com.ssy.lingxi.member.merchant.api.feign.paas.RoleControllerFeign;
import com.ssy.lingxi.member.merchant.api.model.vo.paas.MemberConfigLabelVO;
import com.ssy.lingxi.member.merchant.api.model.vo.paas.MemberConfigQueryVO;
import com.ssy.lingxi.member.merchant.api.model.vo.paas.MemberConfigVO;
import com.ssy.lingxi.member.merchant.api.model.vo.paas.RoleConfigVO;
import com.ssy.lingxi.system.dao.MemberConfigLabelRepository;
import com.ssy.lingxi.system.dao.MemberConfigRepository;
import com.ssy.lingxi.system.dao.MemberConfigRoleRepository;
import com.ssy.lingxi.system.dao.RoleRepository;
import com.ssy.lingxi.system.dto.request.*;
import com.ssy.lingxi.system.dto.response.MiddlegroundUserLoginResponse;
import com.ssy.lingxi.system.entity.MemberConfig;
import com.ssy.lingxi.system.entity.MemberConfigLabel;
import com.ssy.lingxi.system.entity.MemberConfigRole;
import com.ssy.lingxi.system.entity.Role;
import com.ssy.lingxi.system.model.constant.MemberConfigCheckRuleEnum;
import com.ssy.lingxi.system.model.request.IdVO;
import com.ssy.lingxi.system.model.request.MemberConfigAddVO;
import com.ssy.lingxi.system.model.request.MemberConfigLabelAddVO;
import com.ssy.lingxi.system.model.request.MemberConfigUpdateVO;
import com.ssy.lingxi.system.model.response.MemberConfigGetVO;
import com.ssy.lingxi.system.model.response.MemberConfigLabelGetVO;
import com.ssy.lingxi.system.model.response.MemberConfigTagVO;
import com.ssy.lingxi.system.service.MemberConfigService;
import com.ssy.lingxi.system.utils.UserDetailsUtil;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Service
public class MemberConfigServiceImpl implements MemberConfigService {
    @Resource
    MemberConfigRepository memberConfigRepository;

    @Resource
    MemberConfigLabelRepository memberConfigLabelRepository;

    @Resource
    UserDetailsUtil userDetailsUtil;

    @Resource
    MemberConfigControllerFeign memberConfigControllerFeign;

    @Resource
    MemberConfigRoleRepository memberConfigRoleRepository;

    @Resource
    private RoleRepository roleRepository;
    
    @Resource
    private RoleControllerFeign roleControllerFeign;

    /**
     * 查询会员注册资料标签列表
     *
     * @return 查询结果
     */
    @Override
    public Wrapper<List<MemberConfigTagVO>> getMemberConfigTagList() {
        List<MemberConfigTagVO> tagVOList = Arrays.stream(MemberConfigTagEnum.values()).sorted(Comparator.comparingInt(MemberConfigTagEnum::getCode)).map(memberConfigTagEnum -> new MemberConfigTagVO(memberConfigTagEnum.getCode(), memberConfigTagEnum.getTagName())).collect(Collectors.toList());
        tagVOList.add(0, new MemberConfigTagVO(0, ""));
        return Wrapper.success(tagVOList);
    }

    /**
     * 查询会员注册资料校验规则列表
     *
     * @return 查询结果
     */
    @Override
    public Wrapper<List<MemberConfigTagVO>> getMemberConfigCheckRuleList() {
        List<MemberConfigTagVO> tagVOList = Arrays.stream(MemberConfigCheckRuleEnum.values()).sorted(Comparator.comparingInt(MemberConfigCheckRuleEnum::getCode)).map(memberConfigCheckRuleEnum -> new MemberConfigTagVO(memberConfigCheckRuleEnum.getCode(), memberConfigCheckRuleEnum.getRuleName())).collect(Collectors.toList());
        tagVOList.add(0, new MemberConfigTagVO(0, ""));
        return Wrapper.success(tagVOList);
    }

    @Transactional
    @Override
    public Wrapper<Void> addMember(MemberConfigAddVO configVO, HttpServletRequest httpServletRequest) {
        MiddlegroundUserLoginResponse loginUserDetails = userDetailsUtil.getLoginUserDetails(httpServletRequest);
        if(configVO.getTagEnum() == null) {
            configVO.setTagEnum(0);
        }

        if(configVO.getRuleEnum() == null) {
            configVO.setRuleEnum(0);
        }

        if(configVO.getFieldName().contains(" ")) {
            return Wrapper.fail("字段名称不能包含空格");
        }

        List<String> fieldTypeList = Stream.of("string", "long", "upload", "checkbox", "radio", "select", "area").collect(Collectors.toList());
        if(!StringUtils.hasLength(configVO.getFieldType()) || !fieldTypeList.contains(configVO.getFieldType())) {
            return Wrapper.fail("字段类型目前仅支持：string、long、upload、checkbox、radio、select、area 类型");
        }

        if(("select".equals(configVO.getFieldType()) || "radio".equals(configVO.getFieldType()) || "checkbox".equals(configVO.getFieldType())) && CollectionUtils.isEmpty(configVO.getFieldEnum())) {
            return Wrapper.fail(configVO.getFieldType() + " 标签枚举值不能为空");
        }

        if(!CollectionUtils.isEmpty(configVO.getFieldEnum())) {
            List<String> labelValues = configVO.getFieldEnum().stream().map(a -> a.getLabel().trim()).collect(Collectors.toList());
            if(labelValues.size() != labelValues.stream().distinct().count()) {
                return Wrapper.fail("字段类型值不能重复");
            }

            int i = 1;
            for (MemberConfigLabelAddVO label : configVO.getFieldEnum()) {
                label.setOrder(1);
                i++;
            }
        }

        MemberConfig memberConfig = new MemberConfig();
        memberConfig.setCreateRoleId(loginUserDetails.getId());
        memberConfig.setCreateTime(System.currentTimeMillis());
        memberConfig.setFieldName(configVO.getFieldName());
        memberConfig.setAnnotationName(configVO.getAnnotationName());
        memberConfig.setFieldType(configVO.getFieldType());
        memberConfig.setAttr(configVO.getAttr() == null ? new HashMap<>() : configVO.getAttr());
        memberConfig.setFieldLength(configVO.getFieldLength() == null ? 0 : configVO.getFieldLength());
        memberConfig.setIsNullState(configVO.getIsNullState() == null ? 0 : configVO.getIsNullState());
        memberConfig.setGroupName(configVO.getGroupName());
        memberConfig.setSort(configVO.getSort());
        memberConfig.setState(CommonConstant.State.STATE_START);
        memberConfig.setHelp(StringUtils.hasLength(configVO.getHelp()) ? configVO.getHelp() : "");
        memberConfig.setTagEnum(configVO.getTagEnum());
        memberConfig.setValidate(configVO.getValidate());
        memberConfig.setRuleEnum(configVO.getRuleEnum());

        MemberConfigVO memberConfigVO = new MemberConfigVO();
        memberConfigVO.setFieldName(memberConfig.getFieldName());
        memberConfigVO.setFieldLocalName(memberConfig.getAnnotationName());
        memberConfigVO.setFieldType(memberConfig.getFieldType());
        memberConfigVO.setFieldEmpty(memberConfig.getIsNullState());
        memberConfigVO.setFieldLength(memberConfig.getFieldLength());
        memberConfigVO.setGroupName(memberConfig.getGroupName());
        memberConfigVO.setFieldOrder(memberConfig.getSort());
        memberConfigVO.setFieldStatus(CommonConstant.State.STATE_START);
        memberConfigVO.setFieldRemark(memberConfig.getHelp());
        memberConfigVO.setTagEnum(memberConfig.getTagEnum());
        memberConfigVO.setValidate(memberConfig.getValidate());
        memberConfigVO.setRuleEnum(memberConfig.getRuleEnum());
        memberConfigVO.setAttr(memberConfig.getAttr());
        memberConfigVO.setFieldEnum(CollectionUtils.isEmpty(configVO.getFieldEnum()) ? new ArrayList<>() : configVO.getFieldEnum().stream().map(item -> new MemberConfigLabelVO(item.getLabel().trim(), item.getOrder())).collect(Collectors.toList()));
        memberConfigVO.setId(0L);

        Wrapper<MemberConfigQueryVO> wrapper = memberConfigControllerFeign.addMemberDetail(memberConfigVO);
        if(ResponseCode.SUCCESS.getCode()!= wrapper.getCode()){
            return Wrapper.fail(wrapper.getCode(), wrapper.getMessage());
        }
        memberConfig.setId(wrapper.getData().getId());
        memberConfigRepository.saveAndFlush(memberConfig);

        if(!CollectionUtils.isEmpty(wrapper.getData().getFieldEnum())) {
            List<MemberConfigLabel> labels = wrapper.getData().getFieldEnum().stream().map(label -> {
                MemberConfigLabel configLabel = new MemberConfigLabel();
                configLabel.setId(label.getId());
                configLabel.setMemberConfigId(memberConfig.getId());
                configLabel.setLabelValue(label.getLabel());
                configLabel.setLabelOrder(label.getOrder());
                return configLabel;
            }).collect(Collectors.toList());
            memberConfigLabelRepository.saveAll(labels);
        }

        return Wrapper.success();
    }

    @Transactional
    @Override
    public Wrapper<Void> updateMember(MemberConfigUpdateVO updateVO) {
        if(updateVO.getTagEnum() == null) {
            updateVO.setTagEnum(0);
        }

        if(updateVO.getRuleEnum() == null) {
            updateVO.setRuleEnum(0);
        }

        if(updateVO.getFieldName().contains(" ")) {
            return Wrapper.fail("字段名称不能包含空格");
        }

        List<String> fieldTypeList = Stream.of("string", "long", "upload", "checkbox", "radio", "select", "area").collect(Collectors.toList());
        if(!StringUtils.hasLength(updateVO.getFieldType()) || !fieldTypeList.contains(updateVO.getFieldType())) {
            return Wrapper.fail("字段类型目前仅支持：string、long、upload、checkbox、radio、select、area 类型");
        }

        if(("select".equals(updateVO.getFieldType()) || "radio".equals(updateVO.getFieldType()) || "checkbox".equals(updateVO.getFieldType())) && CollectionUtils.isEmpty(updateVO.getFieldEnum())) {
            return Wrapper.fail(updateVO.getFieldType() + " 标签枚举值不能为空");
        }

        if(!CollectionUtils.isEmpty(updateVO.getFieldEnum())) {
            List<String> labelValues = updateVO.getFieldEnum().stream().map(a -> a.getLabel().trim()).collect(Collectors.toList());
            if(labelValues.size() != labelValues.stream().distinct().count()) {
                return Wrapper.fail("字段类型值不能重复");
            }

            int i = 1;
            for (MemberConfigLabelAddVO label : updateVO.getFieldEnum()) {
                label.setOrder(1);
                i++;
            }
        }

        MemberConfig memberConfig = memberConfigRepository.findById(updateVO.getId()).orElse(null);
        if(memberConfig == null) {
            return Wrapper.fail(ResponseCode.REQUEST_PARAM_CHECK_FAILED, "数据记录不存在");
        }

        if(updateVO.getFieldLength() < memberConfig.getFieldLength()) {
            return Wrapper.fail(ResponseCode.REQUEST_PARAM_CHECK_FAILED, "字段长度不能小于原有字段长度");
        }

        memberConfig.setUpdateTime(System.currentTimeMillis());
        memberConfig.setFieldName(updateVO.getFieldName());
        memberConfig.setAnnotationName(updateVO.getAnnotationName());
        memberConfig.setFieldType(updateVO.getFieldType());
        memberConfig.setAttr(updateVO.getAttr() == null ? new HashMap<>() : updateVO.getAttr());
        memberConfig.setFieldLength(updateVO.getFieldLength() == null ? 0 : updateVO.getFieldLength());
        memberConfig.setIsNullState(updateVO.getIsNullState() == null ? 0 : updateVO.getIsNullState());
        memberConfig.setGroupName(updateVO.getGroupName());
        memberConfig.setSort(updateVO.getSort());
        memberConfig.setState(CommonConstant.State.STATE_START);
        memberConfig.setHelp(StringUtils.hasLength(updateVO.getHelp()) ? updateVO.getHelp() : "");
        memberConfig.setTagEnum(updateVO.getTagEnum());
        memberConfig.setValidate(updateVO.getValidate());
        memberConfig.setRuleEnum(updateVO.getRuleEnum());

        MemberConfigVO memberConfigVO = new MemberConfigVO();
        memberConfigVO.setId(memberConfig.getId());
        memberConfigVO.setFieldName(memberConfig.getFieldName());
        memberConfigVO.setFieldLocalName(memberConfig.getAnnotationName());
        memberConfigVO.setFieldType(memberConfig.getFieldType());
        memberConfigVO.setFieldEmpty(memberConfig.getIsNullState());
        memberConfigVO.setFieldLength(memberConfig.getFieldLength());
        memberConfigVO.setGroupName(memberConfig.getGroupName());
        memberConfigVO.setFieldOrder(memberConfig.getSort());
        memberConfigVO.setFieldStatus(CommonConstant.State.STATE_START);
        memberConfigVO.setFieldRemark(memberConfig.getHelp());
        memberConfigVO.setTagEnum(memberConfig.getTagEnum());
        memberConfigVO.setValidate(memberConfig.getValidate());
        memberConfigVO.setRuleEnum(memberConfig.getRuleEnum());
        memberConfigVO.setAttr(memberConfig.getAttr());
        memberConfigVO.setFieldEnum(CollectionUtils.isEmpty(updateVO.getFieldEnum()) ? new ArrayList<>() : updateVO.getFieldEnum().stream().map(item -> new MemberConfigLabelVO(item.getLabel().trim(), item.getOrder())).collect(Collectors.toList()));

        Wrapper<MemberConfigQueryVO> wrapper = memberConfigControllerFeign.updateMemberDetail(memberConfigVO);
        if(ResponseCode.SUCCESS.getCode()!= wrapper.getCode()){
            return Wrapper.fail(wrapper.getCode(), wrapper.getMessage());
        }

        memberConfigRepository.saveAndFlush(memberConfig);

        //标签枚举：删除后再新增
        memberConfigLabelRepository.deleteByMemberConfigId(memberConfig.getId());

        if(!CollectionUtils.isEmpty(wrapper.getData().getFieldEnum())) {
            List<MemberConfigLabel> labels = wrapper.getData().getFieldEnum().stream().map(label -> {
                MemberConfigLabel configLabel = new MemberConfigLabel();
                configLabel.setId(label.getId());
                configLabel.setMemberConfigId(memberConfig.getId());
                configLabel.setLabelValue(label.getLabel());
                configLabel.setLabelOrder(label.getOrder());
                return configLabel;
            }).collect(Collectors.toList());
            memberConfigLabelRepository.saveAll(labels);
        }

        return Wrapper.success();
    }

    /**
     * 查询会员注册资料信息
     *
     * @param idVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<MemberConfigGetVO> getMemberConfig(IdVO idVO) {
        MemberConfig memberConfig = memberConfigRepository.findById(idVO.getId()).orElse(null);
        if(memberConfig == null) {
            return Wrapper.fail("注册资料不存在");
        }

        MemberConfigGetVO getVO = new MemberConfigGetVO();
        getVO.setId(memberConfig.getId());
        getVO.setFieldName(memberConfig.getFieldName());
        getVO.setAnnotationName(memberConfig.getAnnotationName());
        getVO.setFieldType(memberConfig.getFieldType());
        getVO.setAttr(memberConfig.getAttr());
        getVO.setFieldLength(memberConfig.getFieldLength() == null ? 0 : memberConfig.getFieldLength());
        getVO.setIsNullState(memberConfig.getIsNullState() == null ? 0 : memberConfig.getIsNullState());
        getVO.setGroupName(memberConfig.getGroupName());
        getVO.setSort(memberConfig.getSort());
        getVO.setHelp(StringUtils.hasLength(memberConfig.getHelp()) ? memberConfig.getHelp() : "");
        getVO.setTagEnum(memberConfig.getTagEnum());
        getVO.setValidate(memberConfig.getValidate());
        getVO.setRuleEnum(memberConfig.getRuleEnum());

        List<MemberConfigLabel> labels = memberConfigLabelRepository.findByMemberConfigId(memberConfig.getId());
        getVO.setFieldEnum(CollectionUtils.isEmpty(labels) ? new ArrayList<>() : labels.stream().map(label -> {
            MemberConfigLabelGetVO labelGetVO = new MemberConfigLabelGetVO();
            labelGetVO.setValue(label.getId());
            labelGetVO.setLabel(label.getLabelValue());
            labelGetVO.setOrder(label.getLabelOrder());
            return labelGetVO;
        }).collect(Collectors.toList()));

        return Wrapper.success(getVO);
    }

    @Override
    public Wrapper<PageData<MemberConfig>> memberList(MemberListRequest request) {
        MemberConfig memberConfig=new MemberConfig();
        memberConfig.setAnnotationName(request.getName());
        ExampleMatcher matcher=ExampleMatcher.matching().withMatcher("annotationName", ExampleMatcher.GenericPropertyMatchers.contains());
        PageRequest of = PageRequest.of(request.getCurrent(), request.getPageSize(), Sort.by("id").ascending());
        Page<MemberConfig> all = memberConfigRepository.findAll(Example.of(memberConfig,matcher),of);

        all.getContent().forEach(c -> {
            if(c.getTagEnum() == null) {
                c.setTagEnum(0);
            }
        });

        return Wrapper.success(new PageData<>(all.getTotalElements(), all.getContent()));
    }

    /**
     * 删除会员字段配置
     *
     * @param request 接口参数
     */
    @Transactional
    @Override
    public Wrapper<Void> deleteMember(DeleteMemberConfigRequest request) {
        MemberConfig memberConfig = memberConfigRepository.findById(request.getId()).orElse(null);
        if (memberConfig == null) {
            return Wrapper.fail(ResponseCode.RECORDS_DON_T_EXIST);
        }

        if (!memberConfig.getState().equals(CommonConstant.State.STATE_STOP)) {
            return Wrapper.fail(ResponseCode.MEMBER_START_NOT_ALLOW);
        }

        List<MemberConfigRole> configRoles = memberConfigRoleRepository.findByMemberConfigId(memberConfig.getId());
        if(!CollectionUtils.isEmpty(configRoles)) {
            List<Long> roleIds = configRoles.stream().map(MemberConfigRole::getRoleId).distinct().collect(Collectors.toList());
            List<Role> roleList = roleRepository.findAllById(roleIds);
            if(!CollectionUtils.isEmpty(roleList)) {
                String roleNames = roleList.stream().map(Role::getName).collect(Collectors.joining(","));
                return Wrapper.fail("角色：" + roleNames + " 已经关联了此注册资料，请先解除关联");
            }
        }


        MemberConfigVO memberConfigVO = new MemberConfigVO();
        memberConfigVO.setId(request.getId());
        Wrapper<?> result = memberConfigControllerFeign.deleteMemberDetail(memberConfigVO);
        if(result.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(result.getCode(), result.getMessage());
        }

        memberConfigLabelRepository.deleteByMemberConfigId(memberConfig.getId());
        memberConfigRepository.delete(memberConfig);

        return Wrapper.success();
    }

    /**
     * 停用启用会员字段配置状态
     *
     * @param request 接口参数
     */
    @Transactional
    @Override
    public Wrapper<Void> startRoStopMember(StartRoStopMemberRequest request) {
        MemberConfig memberConfig = memberConfigRepository.findById(request.getId()).orElse(null);
        if (memberConfig == null) {
            return Wrapper.fail(ResponseCode.RECORDS_DON_T_EXIST);
        }

        List<MemberConfigRole> configRoles = memberConfigRoleRepository.findByMemberConfigId(memberConfig.getId());
        if(!CollectionUtils.isEmpty(configRoles)) {
            List<Long> roleIds = configRoles.stream().map(MemberConfigRole::getRoleId).distinct().collect(Collectors.toList());
            List<Role> roleList = roleRepository.findAllById(roleIds);
            if(!CollectionUtils.isEmpty(roleList)) {
                String roleNames = roleList.stream().map(Role::getName).collect(Collectors.joining(","));
                return Wrapper.fail("角色：" + roleNames + " 已经关联了此注册资料，请先解除关联");
            }
        }

        MemberConfigVO memberConfigVO = new MemberConfigVO();
        memberConfigVO.setId(request.getId());
        memberConfigVO.setFieldStatus(request.getState());
        Wrapper<?> result = memberConfigControllerFeign.updateMemberDetailStatus(memberConfigVO);
        if(result.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(result.getCode(), result.getMessage());
        }

        memberConfig.setState(request.getState());
        memberConfigRepository.save(memberConfig);

        return Wrapper.success();
    }

    /**
     * 根据角色ID查询会员字段配置列表
     * @param request 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<List<MemberConfig>> memberByRoleIdList(MemberByRoleIdListRequest request) {
        List<Long> collect = memberConfigRoleRepository.findByRoleId(request.getRoleId()).stream().map(MemberConfigRole::getMemberConfigId).collect(Collectors.toList());
        List<MemberConfig> allById = memberConfigRepository.findAllById(collect);
        List<MemberConfig> list = allById.stream().filter(v -> v.getState().equals(CommonConstant.State.STATE_START)).collect(Collectors.toList());
        return Wrapper.success(list);
    }

    /**
     * 配置会员角色和字段关联
     *
     * @param request 接口参数
     */
    @Transactional
    @Override
    public Wrapper<Void> setRoleConfig(SetRoleConfigRequest request) {
        if(!CollectionUtils.isEmpty(request.getConfigIds())) {
            List<MemberConfig> configList = memberConfigRepository.findAll().stream().filter(memberConfig -> request.getConfigIds().contains(memberConfig.getId())).collect(Collectors.toList());
            if(configList.size() != request.getConfigIds().size()) {
                return Wrapper.fail("注册资料不存在");
            }

            List<Integer> tagEnums = configList.stream().filter(config -> config.getTagEnum() != null && config.getTagEnum() > 0).map(MemberConfig::getTagEnum).collect(Collectors.toList());
            if(tagEnums.size() != tagEnums.stream().distinct().count()) {
                return Wrapper.fail("关联的注册资料中包含的重复的标签字段");
            }

            //必须关联公司名称
            if(configList.stream().noneMatch(config -> config.getTagEnum().equals(MemberConfigTagEnum.Member_Name.getCode()))) {
                return Wrapper.fail("角色必须关联标签为'公司名称'的注册资料");
            }
        }

        RoleConfigVO roleConfigVO=new RoleConfigVO();
        roleConfigVO.setConfigIds(CollectionUtils.isEmpty(request.getConfigIds()) ? new ArrayList<>() : request.getConfigIds());
        roleConfigVO.setRoleId(request.getRoleId());
        Wrapper<?> wrapper = roleControllerFeign.setRoleConfig(roleConfigVO);
        if(wrapper.getCode() != ResponseCode.SUCCESS.getCode()) {
            return Wrapper.fail(wrapper.getCode(), wrapper.getMessage());
        }

        List<MemberConfigRole> list=new ArrayList<>();
        memberConfigRoleRepository.deleteAllByRoleIdEquals(request.getRoleId());
        request.getConfigIds().forEach(id->{
            MemberConfigRole memberConfigRole=new MemberConfigRole();
            memberConfigRole.setMemberConfigId(id);
            memberConfigRole.setRoleId(request.getRoleId());
            list.add(memberConfigRole);
        });
        memberConfigRoleRepository.saveAll(list);

        return Wrapper.success();
    }
}
